/*
 * Copyright (C) 2009 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.rockchip.audiotest;

import android.app.Activity;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.os.Debug;
import android.os.Handler;
import android.text.TextUtils;
import android.util.Log;
import android.view.View;
import android.widget.Toast;
import android.widget.Button;
import android.widget.ImageButton;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.ProgressBar;
import android.widget.TextView;
import android.text.method.ScrollingMovementMethod;
import android.widget.EditText;
import android.widget.CheckBox;
import android.app.Dialog;
import android.media.AudioManager;
import android.content.Context;
import java.util.ArrayList;
import android.media.AudioPort;
import android.media.AudioAttributes;
import android.media.AudioDeviceAttributes;
import android.media.AudioDeviceInfo;
import android.media.audiopolicy.AudioProductStrategy;
import java.util.Arrays;
import java.util.List;
import android.util.Slog;
import android.view.View.OnClickListener;
import android.widget.ListView;
import android.widget.AdapterView;
import android.widget.SimpleAdapter;
import java.util.HashMap;
import android.media.MediaRecorder;

public class AudioMangeActivity extends Activity {
    private static final boolean DBG = false;
    private static final String TAG = "AudioMangeActivity";
    AudioManager audioManager;
    ListView mFileListView;
    private static final String DEVICE_NAME = "devicename";
    private static final String DEVICE_INFO = "deviceinfo";
    private ArrayList<HashMap<String, Object>> mArrlist;
    AudioDeviceInfo moutputDeviceinfo;
    AudioDeviceInfo minputDeviceinfo;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_audiomanager);
        initwidgets();
        init(getApplicationContext());
    }

    void initwidgets() {
        Button button = (Button) findViewById(R.id.listdevices_button);
        button.setOnClickListener(new OnClickListener() {
            public void onClick(View v) {
                updateDevicesList();
            }
        });

        button = (Button) findViewById(R.id.selectspeaker_button);
        button.setOnClickListener(new OnClickListener() {
            public void onClick(View v) {
                Log.d(TAG, "setSpeakerOut()");
                setSpeakerOut();
            }
        });

        button = (Button) findViewById(R.id.selectheadset_button);
        button.setOnClickListener(new OnClickListener() {
            public void onClick(View v) {
                Log.d(TAG, "setHeadSetOut()");
                setHeadSetOut();
            }
        });

        button = (Button) findViewById(R.id.selecthdmi_button);
        button.setOnClickListener(new OnClickListener() {
            public void onClick(View v) {
                Log.d(TAG, "setHdmiOut()");
                setHdmiOut();
            }
        });
    
        button = (Button) findViewById(R.id.selectusb0_button);
        button.setOnClickListener(new OnClickListener() {
            public void onClick(View v) {
                Log.d(TAG, "setUsbOut(0)");
                setUsbOut(0);
            }
        });
        button = (Button) findViewById(R.id.selectusb1_button);
        button.setOnClickListener(new OnClickListener() {
            public void onClick(View v) {
                Log.d(TAG, "setUsbOut(1)");
                setUsbOut(1);
            }
        });

        button = (Button) findViewById(R.id.selectoutput_button);
        button.setOnClickListener(new OnClickListener() {
            public void onClick(View v) {
                Log.d(TAG, "setoutput device");
                if (moutputDeviceinfo != null) {
                    setPreferredDevicesForStrategy(getStrageForMedia(), moutputDeviceinfo);
                } else {
                    String toast_text = getResources().getString(R.string.info_none_output);
                    Toast.makeText(AudioMangeActivity.this, toast_text, Toast.LENGTH_SHORT).show();
                }
            }
        });

        button = (Button) findViewById(R.id.selectinput_button);
        button.setOnClickListener(new OnClickListener() {
            public void onClick(View v) {
                Log.d(TAG, "setinput device");
                if (minputDeviceinfo != null) {
                    setPreferredDeviceForCapture(minputDeviceinfo);
                } else {
                    String toast_text = getResources().getString(R.string.info_none_input);
                    Toast.makeText(AudioMangeActivity.this, toast_text, Toast.LENGTH_SHORT).show();
                }
            }
        });

        initinputwidgets();
        mFileListView = (ListView) findViewById(R.id.devices_list);
        mFileListView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
                    @Override
                    public void onItemClick(AdapterView<?> arg0, View view, int arg2, long arg3) {
                            Intent intent = new Intent();
                            HashMap<String, Object> map = (HashMap<String, Object>) mFileListView.getItemAtPosition(arg2);
                            if (map != null && map.get(DEVICE_INFO) != null) {
                                AudioDeviceInfo deviceinfo = (AudioDeviceInfo)map.get(DEVICE_INFO);
                                Log.d(TAG, "you have select: " +  deviceinfo);
                                if (deviceinfo.isSource()) {
                                    minputDeviceinfo = deviceinfo;
                                    TextView textView =  (TextView) findViewById(R.id.selectinput_textview);
                                    textView.setText(devicestostring(minputDeviceinfo));
                                } else {
                                    moutputDeviceinfo = deviceinfo;
                                    TextView textView =  (TextView) findViewById(R.id.selectoutput_textview);
                                    textView.setText(devicestostring(moutputDeviceinfo));
                                }
                            }
                        }
                    });
    }

    String devicestostring(AudioDeviceInfo device)
    {
        return "id: " + String.format("%2d", device.getId()) + "  type: " + String.format("%s", typeToString(device.getType())) + " address: " + device.getAddress();
    }

    void updateDevicesList() {
        int i, j = 0;
        AudioDeviceInfo[] devices_out = audioManager.getDevices(AudioManager.GET_DEVICES_OUTPUTS);
        AudioDeviceInfo[] devices_in = audioManager.getDevices(AudioManager.GET_DEVICES_INPUTS);

        mArrlist = new ArrayList<HashMap<String, Object>>();
        for(i = 0; i < devices_out.length; i++ ) {
            Slog.d(TAG, "output devices :" + i + " is    " + devices_out[i].getType());
            HashMap<String, Object> map = new HashMap<String, Object>();
            map.put(DEVICE_NAME, j + "  " + devicestostring(devices_out[i]));
            map.put(DEVICE_INFO, devices_out[i]);
            j++;
            mArrlist.add(map);
        }

        for(i = 0; i < devices_in.length; i++ ) {
            Slog.d(TAG, "intput devices :" + i + " is    " + devices_in[i].getType());
            HashMap<String, Object> map = new HashMap<String, Object>();
            map.put(DEVICE_NAME, j + "  " + devicestostring(devices_in[i]));
            map.put(DEVICE_INFO, devices_in[i]);
            j++;
            mArrlist.add(map);
        }

        SimpleAdapter adapter = new SimpleAdapter(this, mArrlist,
                                                  R.layout.deviceslist_adapter,
                                                  new String[]{DEVICE_NAME},
                                                  new int[]{R.id.devicename_textview});
        mFileListView.setAdapter(adapter);
    }

    void initinputwidgets() {
        Button button = (Button) findViewById(R.id.selecthdmi_in_button);
        button.setOnClickListener(new OnClickListener() {
            public void onClick(View v) {
                Log.d(TAG, "setHdmiIn()");
            }
        });

        button = (Button) findViewById(R.id.selectmic_in_button);
        button.setOnClickListener(new OnClickListener() {
            public void onClick(View v) {
                Log.d(TAG, "setMicIn()");
                
            }
        });

        button = (Button) findViewById(R.id.selectheadset_in_button);
        button.setOnClickListener(new OnClickListener() {
            public void onClick(View v) {
                Log.d(TAG, "setHeadsetIn()");
                
            }
        });

        button = (Button) findViewById(R.id.selectusb0_in_button);
        button.setOnClickListener(new OnClickListener() {
            public void onClick(View v) {
                Log.d(TAG, "setUsb0In()");
                
            }
        });

        button = (Button) findViewById(R.id.selectusb1_in_button);
        button.setOnClickListener(new OnClickListener() {
            public void onClick(View v) {
                Log.d(TAG, "setUsb1In()");
                
            }
        });
    }

    void init(Context context) {
        audioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);
        if (audioManager != null) {
            Log.d(TAG, "AudioManager open successfull");
            updateDevicesList();
        }
    }

    void list_alldevices()
    {
        AudioDeviceInfo[] devices_out;
        AudioDeviceInfo[] devices_in;
        int i;

        devices_out = audioManager.getDevices(AudioManager.GET_DEVICES_OUTPUTS);
        devices_in =  audioManager.getDevices(AudioManager.GET_DEVICES_OUTPUTS);
        for(i = 0; i < devices_out.length; i++ ) {
            Slog.d(TAG, "output devices :" + i + " is    " + devices_out[i].getType());

        }

        for(i = 0; i < devices_in.length; i++ ) {
            Slog.d(TAG, "intput devices :" + i + " is    " + devices_in[i].getType());

        }
    }

    void setUsbOut(int index)
    {
        AudioDeviceInfo usbout = GetspecifiedOutPutDevice(AudioDeviceInfo.TYPE_USB_DEVICE, index);
        if (null == usbout) {
            usbout = GetspecifiedOutPutDevice(AudioDeviceInfo.TYPE_USB_ACCESSORY, index);
            if (null == usbout) {
                usbout = GetspecifiedOutPutDevice(AudioDeviceInfo.TYPE_USB_HEADSET, index);
            }
        }
        if (null == usbout) {
            Log.i(TAG, "there is no usb out device index " + index);
            return;
        }
        Log.i(TAG, "setting out device to " + usbout);
        setPreferredDevicesForStrategy(getStrageForMedia(), usbout);
    }

    void setHdmiOut()
    {
        AudioDeviceInfo hdmiout = GetspecifiedOutPutDevice(AudioDeviceInfo.TYPE_HDMI, 0);
        if (null == hdmiout) {
            Log.i(TAG, "there is no hdmi out device");
            return;
        }
        Log.i(TAG, "setting out device to " + hdmiout);
        setPreferredDevicesForStrategy(getStrageForMedia(), hdmiout);
    }

    void setSpeakerOut()
    {
        AudioDeviceInfo speaker = GetspecifiedOutPutDevice(AudioDeviceInfo.TYPE_BUILTIN_SPEAKER, 0);
        if (null == speaker) {
            Log.i(TAG, "there is no speaker device");
            return;
        }
        Log.i(TAG, "setting out device to " + speaker);
        setPreferredDevicesForStrategy(getStrageForMedia(), speaker);
    }

    void setHeadSetOut()
    {
        AudioDeviceInfo headset = GetspecifiedOutPutDevice(AudioDeviceInfo.TYPE_WIRED_HEADPHONES, 0);
        if (null == headset) {
            headset = GetspecifiedOutPutDevice(AudioDeviceInfo.TYPE_WIRED_HEADSET, 0);
        }
        if (null == headset) {
            Log.i(TAG, "there is no headset device");
            return;
        }
        Log.i(TAG, "setting out device to " + headset);
        setPreferredDevicesForStrategy(getStrageForMedia(), headset);
    }

    AudioDeviceInfo GetspecifiedOutPutDevice(int type, int index)
    {
        AudioDeviceInfo info;
        int i;
        AudioDeviceInfo[] devices = audioManager.getDevices(AudioManager.GET_DEVICES_OUTPUTS);
        if (devices.length <= 0) {
            Log.i(TAG, "there is no output device");
            return null;
        }

        for(i = 0; i < devices.length; i++ ) {
            info = devices[i];
            if (type == info.getType()) {
                if (index -- <= 0) {
                    return info;
                }
            }
        }
        Log.i(TAG, "there is no output device for type " + type + " index " + index);
        return null;
    }

    AudioDeviceInfo GetspecifiedInPutDevice(int type, int index)
    {
        AudioDeviceInfo info;
        int i;
        AudioDeviceInfo[] devices = audioManager.getDevices(AudioManager.GET_DEVICES_INPUTS);
        if (devices.length <= 0) {
            Log.i(TAG, "there is no input device");
            return null;
        }
        for(i = 0; i < devices.length; i++ ) {
            info = devices[i];
            if (type == info.getType()) {
                if (index -- <= 0) {
                    return info;
                }
            }
        }
        Log.i(TAG, "there is no input device for type " + type + " index " + index);
        return null;
    }

    AudioProductStrategy getStrageForMedia()
    {
        AudioAttributes mediaAttr = new AudioAttributes.Builder().setUsage(AudioAttributes.USAGE_MEDIA).build();
        List<AudioProductStrategy> strategies = AudioProductStrategy.getAudioProductStrategies();
        AudioProductStrategy strategyForMedia = null;
        for (AudioProductStrategy strategy : strategies) {
            //Log.i(TAG, "getStrageForMedia find strategy:" + strategy.toString());
            if (strategy.supportsAudioAttributes(mediaAttr)) {
                strategyForMedia = strategy;
            }
        }
        Log.i(TAG, "getStrageForMedia find strategy: " + strategyForMedia.toString());
        return strategyForMedia;
    }

    boolean setPreferredDevicesForStrategy(AudioProductStrategy strategy, AudioDeviceInfo device)
    {
        AudioDeviceAttributes ada = new AudioDeviceAttributes(device);
        try {
            audioManager.setPreferredDeviceForStrategy(strategy, ada);
            Log.i(TAG, "setPreferredDeviceForStrategy success strategy:" + strategy + " device:" + device);
        } catch (SecurityException e) {
            Log.i(TAG, "setPreferredDeviceForStrategy fail strategy:" + strategy + " device:" + device + ": " + e);
            return false;
        }
        return true;
    }

    boolean setPreferredDeviceForCapture(AudioDeviceInfo device)
    {
        AudioDeviceAttributes ada = new AudioDeviceAttributes(device);
        try {
            audioManager.setPreferredDeviceForCapturePreset(MediaRecorder.AudioSource.MIC, ada);
            Log.i(TAG, "setPreferredDeviceForCapturePreset success AudioSource: MIC" + " device:" + device);
        } catch (SecurityException e) {
            Log.i(TAG, "setPreferredDeviceForCapturePreset fail AudioSource: MIC" + " device:" + device + ": " + e);
            return false;
        }
        return true;
    }

    public String typeToString(int type) {
        switch (type) {
            case AudioDeviceInfo.TYPE_UNKNOWN:
                return "TYPE_UNKNOWN";
            case AudioDeviceInfo.TYPE_BUILTIN_EARPIECE:
                return "TYPE_BUILTIN_EARPIECE";
            case AudioDeviceInfo.TYPE_BUILTIN_SPEAKER:
                return "TYPE_BUILTIN_SPEAKER";
            case AudioDeviceInfo.TYPE_WIRED_HEADSET:
                return "TYPE_WIRED_HEADSET";
            case AudioDeviceInfo.TYPE_WIRED_HEADPHONES:
                return "TYPE_WIRED_HEADPHONES";
            case AudioDeviceInfo.TYPE_LINE_ANALOG:
                return "Unknown";
            case AudioDeviceInfo.TYPE_LINE_DIGITAL:
                return "TYPE_LINE_DIGITAL";
            case AudioDeviceInfo.TYPE_BLUETOOTH_SCO  :
                return "Unknown";
            case AudioDeviceInfo.TYPE_BLUETOOTH_A2DP:
                return "Unknown";
            case AudioDeviceInfo.TYPE_HDMI:
                return "TYPE_HDMI";
            case AudioDeviceInfo.TYPE_HDMI_ARC:
                return "TYPE_HDMI_ARC";
            case AudioDeviceInfo.TYPE_USB_DEVICE:
                return "TYPE_USB_DEVICE";
            case AudioDeviceInfo.TYPE_USB_ACCESSORY:
                return "TYPE_USB_ACCESSORY";
            case AudioDeviceInfo.TYPE_DOCK:
                return "TYPE_DOCK";
            case AudioDeviceInfo.TYPE_FM:
                return "Unknown";
            case AudioDeviceInfo.TYPE_BUILTIN_MIC:
                return "TYPE_BUILTIN_MIC";
            case AudioDeviceInfo.TYPE_FM_TUNER:
                return "TYPE_FM_TUNER";
            case AudioDeviceInfo.TYPE_TV_TUNER:
                return "TYPE_TV_TUNER";
            case AudioDeviceInfo.TYPE_TELEPHONY:
                return "TYPE_TELEPHONY";
            case AudioDeviceInfo.TYPE_AUX_LINE:
                return "TYPE_AUX_LINE";
            case AudioDeviceInfo.TYPE_IP:
                return "TYPE_IP";
            case AudioDeviceInfo.TYPE_BUS:
                return "TYPE_BUS";
            case AudioDeviceInfo.TYPE_USB_HEADSET:
                return "TYPE_USB_HEADSET";
            case AudioDeviceInfo.TYPE_HEARING_AID:
                return "Unknown";
            case AudioDeviceInfo.TYPE_BUILTIN_SPEAKER_SAFE:
                return "Unknown";
            case AudioDeviceInfo.TYPE_REMOTE_SUBMIX:
                return "TYPE_REMOTE_SUBMIX";
            case AudioDeviceInfo.TYPE_BLE_HEADSET:
                return "Unknown";
            case AudioDeviceInfo.TYPE_BLE_SPEAKER:
                return "Unknown";
            case AudioDeviceInfo.TYPE_ECHO_REFERENCE:
                return "TYPE_ECHO_REFERENCE";
            case AudioDeviceInfo.TYPE_HDMI_EARC:
                return "Unknown";
            default:
                return "Unknown";
        }
    }
}